package com.kinsin.kinsinutil


import android.util.Log
import kotlin.collections.firstOrNull
import kotlin.jvm.java
import kotlin.let
import kotlin.run
import kotlin.text.chunked
import kotlin.text.isNotEmpty
import kotlin.text.substringAfterLast

/**
 * 日志工具类
 * @author kinsin
 */
object Logger {
    // 配置参数（线程安全需业务层保证或使用原子类型）
    @JvmStatic
    var isEnabled = true
    @JvmStatic
    var showThreadInfo = false
    @JvmStatic
    var showClassInfo = true
    @JvmStatic
    var tagPrefix = ""
    @JvmStatic
    var maxLogLength = 4000

    // 日志核心方法
    @JvmStatic
    fun log(priority: Int, tag: String, message: String, tr: Throwable?) {
        if (!isEnabled) return

        val fullMessage = buildLogMessage(message)
        val logTag = buildTag(tag)

        printLog(priority, logTag, fullMessage, tr)
    }

    private fun buildLogMessage(message: String): String {
        return buildString {
            if (showThreadInfo) append("[${Thread.currentThread().name}] ")
            if (showClassInfo) append(getCallerInfo())
            append(message)
        }
    }

    private fun buildTag(tag: String) = if (tagPrefix.isNotEmpty()) "$tagPrefix:$tag" else tag

    private fun printLog(priority: Int, tag: String, message: String, tr: Throwable?) {
        val chunks = message.chunked(maxLogLength)
        val totalChunks = chunks.size

        chunks.forEachIndexed { index, chunk ->
            val chunkInfo = if (totalChunks > 1) "[${index + 1}/$totalChunks] " else ""
            Log.println(priority, tag, chunkInfo + chunk)
        }

        tr?.let {
            Log.println(priority, tag, "Exception: " + Log.getStackTraceString(it))
        }
    }

    private fun getCallerInfo(): String {
        if (!showClassInfo) return ""

        val element = Throwable().stackTrace.firstOrNull {
            it.className !in setOf(
                Logger::class.java.name,
                "LoggerKt"
            )
        }
        return element?.run {
            "${className.substringAfterLast('.')}.$methodName($fileName:$lineNumber) "
        } ?: ""
    }


}

// region 自动 TAG 的日志函数（带性能优化）
inline fun logV(message:  String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.VERBOSE, getAutoTag(), message, tr)
}

inline fun logD(message:  String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.DEBUG, getAutoTag(), message, tr)
}

inline fun logI(message:  String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.INFO, getAutoTag(), message, tr)
}

inline fun logW(message:  String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.WARN, getAutoTag(), message, tr)
}

inline fun logE(message:  String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.ERROR, getAutoTag(), message, tr)
}
// endregion

// region 手动 TAG 的日志函数
fun logV(tag: String, message: String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.VERBOSE, tag, message, tr)
}

fun logD(tag: String, message: String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.DEBUG, tag, message, tr)
}

fun logI(tag: String, message: String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.INFO, tag, message, tr)
}

fun logW(tag: String, message: String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.WARN, tag, message, tr)
}

fun logE(tag: String, message: String, tr: Throwable? = null) {
    if (!Logger.isEnabled) return
    Logger.log(Log.ERROR, tag, message, tr)
}
// endregion

// region 工具方法
inline fun getAutoTag(): String {
    return Throwable().stackTrace.firstOrNull {
        it.className !in setOf(
            Logger::class.java.name,
            "LoggerKt"
        )
    }?.className?.substringAfterLast('.') ?: "Unknown"
}
// endregion